home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / cmprss.exe / CPRESS.CPP < prev    next >
C/C++ Source or Header  |  1993-01-26  |  2KB  |  112 lines

  1. #include <string.h>
  2. #include "compress.cls"
  3. #include "type.h"
  4.  
  5. int cpofstream::compress(uchar *inbuff, uint inbuff_len, uchar *outbuff, uchar *hash_tbl[], uint hash_len)
  6.     {
  7. uchar *in_idx=inbuff;
  8. uchar *inbuff_end=inbuff+inbuff_len;
  9. uchar *anchor;
  10. uchar *pat_idx;
  11. uint cnt;
  12. uint gap;
  13. uint c;
  14. uint hash;
  15. uint *ctrl_idx=(uint*)outbuff;
  16. uint ctrl_bits;
  17. uint ctrl_cnt=0;
  18.  
  19. uchar *out_idx=outbuff+sizeof(uint);
  20. uchar *outbuff_end=outbuff+(inbuff_len-48);
  21.  
  22.     if (inbuff_len <= 18)
  23.         {
  24.         memcpy(outbuff,inbuff,inbuff_len);
  25.         return 0-inbuff_len;
  26.         }
  27.  
  28.     hash_len--;
  29.  
  30.     while (in_idx < inbuff_end)
  31.         {
  32.         if (ctrl_cnt++==16)
  33.             {
  34.             *ctrl_idx=ctrl_bits;
  35.             ctrl_cnt=1;
  36.             ctrl_idx=(uint*)out_idx;
  37.             out_idx+=2;
  38.  
  39.             if (out_idx>outbuff_end)
  40.                 {
  41.                 memcpy(outbuff,inbuff,inbuff_len);
  42.                 return 0-inbuff_len;
  43.                 }
  44.             }
  45.         anchor=in_idx;
  46.         c=*in_idx++;
  47.  
  48.         while (in_idx < inbuff_end && *in_idx==c && (in_idx-anchor)<4114)
  49.             in_idx++;
  50.  
  51.         if ((cnt=in_idx-anchor) > 2)
  52.             {
  53.             if (cnt<=18)
  54.                 {
  55.                 *out_idx++=cnt-3;
  56.                 *out_idx++=c;
  57.                 }
  58.             else
  59.                 {
  60.                 cnt-=19;
  61.                 *out_idx++=16+(cnt & 0x0F);
  62.                 *out_idx++=cnt>>4;
  63.                 *out_idx++=c;
  64.                 }
  65.             ctrl_bits=(ctrl_bits<<1) | 1;
  66.             continue;
  67.             }
  68.  
  69.         in_idx=anchor;
  70.         if ((inbuff_end - in_idx) > 2)
  71.             {
  72.             hash=((((in_idx[0] & 15) << 8) | in_idx[1]) ^ ((in_idx[0]>>4) | (in_idx[2]<<4))) & hash_len;
  73.             pat_idx=hash_tbl[hash];
  74.             hash_tbl[hash]=in_idx;
  75.  
  76.             if ((gap=in_idx-pat_idx) <= 4098)
  77.                 {
  78.                 while (in_idx < inbuff_end && pat_idx < anchor && *pat_idx==*in_idx && (in_idx-anchor) < 271)
  79.                     {
  80.                     in_idx++;
  81.                     pat_idx++;
  82.                     }
  83.                 if ((cnt=in_idx-anchor) > 2)
  84.                     {
  85.                     gap-=3;
  86.                     if (cnt<=15)
  87.                         {
  88.                         *out_idx++=(cnt<<4) + (gap & 0x0F);
  89.                         *out_idx++=gap >> 4;
  90.                         }
  91.                     else
  92.                         {
  93.                         *out_idx++=32 + (gap & 0x0F);
  94.                         *out_idx++=gap >> 4;
  95.                         *out_idx++=cnt-16;
  96.                         }
  97.                     ctrl_bits=(ctrl_bits<<1) | 1;
  98.                     continue;
  99.                     }
  100.                 }
  101.             }
  102.         *out_idx++=c;
  103.         in_idx=++anchor;
  104.         ctrl_bits<<=1;
  105.         }
  106.     ctrl_bits<<=(16-ctrl_cnt);
  107.     *ctrl_idx=ctrl_bits;
  108.  
  109.     return out_idx-outbuff;
  110.     }
  111.  
  112.